Add support @Target annotation#2548
Conversation
|
My knowledge of the Apollo Federation is quite limited - but how is the |
This was simply the wrong package name, as mentioned in the link of the description this annotation does not exist yet in the eclipse-microprofile, so a new namespace is needed. Any suggestions? |
I would have just moved the annotation to the Regarding the PR, I barely skimmed trought your test case atleast, but they look bit different to @t1 specification, and having it mixed with federation API does not help it either (amongst other non-trivial GraphQL keywords). Regarding test placement, I would have taken look at both:
|
|
Maybe @t1 can have a look ? |
|
Please also add some short text and examples into the documentation |
|
I wrote an IT to show how I had imagined for this to work; and TODOs on how it does not. I don't quite understand how your solution is intended to work; is it about Federation? That would also be cool, but not what I had on my mind when I wrote #349. Note that there was a flaw in the original suggestion: we can't update the team as an object; we need to update the team id. Here's my test that shows package io.smallrye.graphql.tests.resolvers;
import static org.assertj.core.api.BDDAssertions.then;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.microprofile.graphql.GraphQLApi;
import org.eclipse.microprofile.graphql.Mutation;
import org.eclipse.microprofile.graphql.Name;
import org.eclipse.microprofile.graphql.Query;
import org.eclipse.microprofile.graphql.Source;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit5.ArquillianExtension;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import io.smallrye.graphql.api.federation.Target;
import io.smallrye.graphql.tests.GraphQLAssured;
@ExtendWith(ArquillianExtension.class)
@RunAsClient
public class ResolverTest {
@Deployment
public static WebArchive deployment() {
return ShrinkWrap.create(WebArchive.class, "mutation-target-test.war")
.addAsResource(new StringAsset("mp.graphql.showErrorMessage=*"), "META-INF/microprofile-config.properties")
.addClasses(SuperHero.class, Team.class, SuperHeroResource.class);
}
public static class SuperHero {
private String id;
private String name;
@SuppressWarnings("unused")
public SuperHero() {
}
public SuperHero(String id, String name) {
this.id = id;
this.name = name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class Team {
private String id;
private String name;
@SuppressWarnings("unused")
public Team() {
}
public Team(String id, String name) {
this.id = id;
this.name = name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@GraphQLApi
public static class SuperHeroResource {
private static final Map<String, SuperHero> SUPER_HEROES = Map.of(
"iron-man", new SuperHero("iron-man", "Iron Man"),
"spider-man", new SuperHero("spider-man", "Spider Man")
);
private static final Map<String, Team> TEAMS = Map.of(
"avengers", new Team("avengers", "Avengers")
);
private static final Map<String, String> SUPER_HERO_TEAMS = new HashMap<>(Map.of(
"iron-man", "avengers"
));
@Query
public SuperHero get(String id) {
var superHero = SUPER_HEROES.get(id);
if (superHero == null) {
throw new IllegalArgumentException("unknown super hero; only have " + SUPER_HEROES.keySet());
}
return superHero;
}
public Team team(@Source SuperHero superHero) {
var teamId = SUPER_HERO_TEAMS.get(superHero.id);
if (teamId == null) {
return null;
}
var team = TEAMS.get(teamId);
if (team == null) {
throw new IllegalArgumentException("unknown team; only have " + TEAMS.keySet());
}
return team;
}
@Mutation
public SuperHero update(@Name("superHero") SuperHero patch) {
var superHero = get(patch.getId());
if (patch.getName() != null) {
superHero.setName(patch.getName());
}
return superHero;
}
// TODO this should be unnecessary (see blow)
@Mutation
public void updateTeam(String superHeroId, String teamId) {
SUPER_HERO_TEAMS.put(superHeroId, teamId);
}
@SuppressWarnings("unused")
public void updateTeam(@Target SuperHero superHero, String teamId) {
SUPER_HERO_TEAMS.put(superHero.getId(), teamId);
}
}
@ArquillianResource
URL testingURL;
GraphQLAssured gql;
@BeforeEach
void setUp() {
gql = new GraphQLAssured(testingURL);
}
@Test
public void shouldGetSuperHeroWithTeam() {
var response = gql.post("""
query {
get(id: "iron-man") {
name
team { name }
}
}""");
then(response).isEqualTo("""
{"data":{"get":{"name":"Iron Man","team":{"name":"Avengers"}}}}""");
}
@Test
public void shouldUpdateTeam() {
// TODO this should be unnecessary if we could provide the rating directly with the update mutation below (commented out)
then(gql.post("""
mutation{updateTeam(superHeroId:"spider-man" teamId:"avengers")}""")
).isEqualTo("""
{"data":{"updateTeam":null}}""");
var response = gql
.post("""
mutation {
update (superHero: {
id: "spider-man"
name: "Ultimate Spiderman"
# teamId: "avengers" # <- this is the @Target field
}) {
name
team {name}
}
}""");
then(response).isEqualTo("""
{"data":{"update":{"name":"Ultimate Spiderman","team":{"name":"Avengers"}}}}""");
then(gql.post("""
query { get(id:"spider-man") { team { name }}}""")
).isEqualTo("""
{"data":{"get":{"team":{"name":"Avengers"}}}}""");
}
} |
0b2c8c7 to
fc717b7
Compare
|
Got your point, as needed this too, this is the completely changed PR. A point which needs to be discussed is the design behind InputType, currently i add a separate field targetFields, which may not be necessary, as Operation already extends Field, but currenlty the code does not add any Operation to 'fields' Add also some documentation to the @target annotation, if more is required plz give me a hint where to add it. |
907236d to
6a8dd0d
Compare
|
6a8dd0d to
38ba87f
Compare
Added documentation and small example to the existing typesafe-client-usage.md. |
38ba87f to
a429261
Compare
As discussed on microprofile/microprofile-graphql#349 this add support for @target annotation similar to @source annotation.
@phillip-kruger would be great if you have time to review